#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
//------------------------------------------------------------------------------
#include "getline.h"
#include "getword.h"
#include "table.h"
//------------------------------------------------------------------------------
#define WZMAX	64		//Max size of word
#define LZMAX	512		//Max size of line
//------------------------------------------------------------------------------
int compare(const char *x, const char *y)
{
	return strcmp(x, y);
}

int first(char c)
{
  if(c != ' ') return 1;
  else return 0;
}

int rest(char c)
{
  if(c == ' ') return 1;
  else return 0;
}
//------------------------------------------------------------------------------
Table_T createCharTable(FILE *pFile, Table_T tbl_Char)
{
	void *value;
	char ch[2];
	ch[1] = '\0';
	int *t_val;
	
	do {
		ch[0] = fgetc (pFile);
		if(ch[0] == ' ' || ch[0] == '\n') continue;
		t_val = (int*) malloc(sizeof(int));
		value = Table_get(tbl_Char, ch);
		if (value != NULL)
		{
			memcpy(t_val, value, sizeof(*t_val));
			*t_val = *t_val + 1;
			Table_put(tbl_Char, ch, t_val);
		} else	//value == NULL
		{
			*t_val = 1;
			Table_put(tbl_Char, ch, t_val);
		}
	} while (ch[0] != EOF);
	return tbl_Char;
}


Table_T createLineTable(FILE *pFile, Table_T tbl_Line)
{
	void *value;
	char chLine[LZMAX];
	int szline;// = getline(pFile, chLine, LZMAX);
	int *t_val;
	do {
		szline = getline(pFile, chLine, LZMAX);
		t_val = (int*) malloc(sizeof(int));
		value = Table_get(tbl_Line, chLine);
		if (value != NULL)
		{
			memcpy(t_val, value, sizeof(*t_val));
			*t_val = *t_val + 1;
			Table_put(tbl_Line, chLine, t_val);
		} else	//value == NULL
		{
			*t_val = 1;
			Table_put(tbl_Line, chLine, t_val);
		}
	} while (szline != EOF);
	return tbl_Line;
}

Table_T createWordTable(FILE *pFile, Table_T tbl_Words)
{
	void *value;
	char chWord[WZMAX];
	char chLine[LZMAX];
	int szline;// = getline(pFile, chLine, LZMAX);
	int *t_val;
	do {
		szline = getline(pFile, chLine, LZMAX);
		while(EOF != getword(chLine, chWord, WZMAX, first, rest))
		{
			t_val = (int*) malloc(sizeof(int));
			value = Table_get(tbl_Words, chWord);
			if (value != NULL)
			{
				memcpy(t_val, value, sizeof(*t_val));
				*t_val = *t_val + 1;
				Table_put(tbl_Words, chWord, t_val);
			} else	//value == NULL
			{
				*t_val = 1;
				Table_put(tbl_Words, chWord, t_val);
			}
		}
	} while (szline != EOF);
	return tbl_Words;
}

static int getoption(int argc, char** argv, char opts[][3], char files[][256])
{
	fprintf(stderr, "...getoption\n");
	int i = 0;
	for(i = 1; i < argc; i++)
	{
		if(strcmp("-f", argv[i]) == 0)
		{
			strcpy(&opts[0][0], argv[i]); // "-f");
		}
		else if(strcmp("-a", argv[i]) == 0) strcpy(opts[1], argv[i]); // "-a");
		else if('-' == argv[i][0]) strcpy(opts[2], argv[i]); //"-n");
		else if('+' == argv[i][0]) strcpy(opts[2], argv[i]); //"+n");
		else
		{
			strcpy(*files, argv[i]);
			files++;
		}
		
	}
	*files[0]='\0';
	fprintf(stderr, "___getoption\n");
	return 0;
}

void usage()
{
	fprintf(stdout, "\nThis program read contents in files and print out characters, words, lines with the numbers they appears\n");
	fprintf(stdout, "\nUSAGE: freq [<-n|+n> -f -a] [files ...]\n\n");
}

int main(int argc, char** argv)
{
	/**
	 * This program can accept following option:
	 * 	-n	Print out all data (characters, words, lines) appear less than n times.
	 * 	+n	Print out all data (characters, words, lines) appear more than n times.
	 * 	-f	The program will print out separating file, without this option the program will print all file together.
	 * 	-a	Sort the output base on alphabetical order
	 * 	If there is not file argument, read from stdin.
	 */
	
	char opts[3][3];
	char files[argc][256];
	
	FILE * pFile;
	char *tmp_fname = "tmp_file";
	char szString[LZMAX];
	int i = 0;
	int val;	// -n|+n
	int sort = 0;	//is sort?
	
	//init data for opts[][]:
	opts[0][0]='\0';
	opts[1][0]='\0';
	opts[2][0]='\0';
	
	if(argc < 2)
	{
		usage();
		return 0;
	}
	//parse options
	getoption(argc, argv, opts, files);
	
	if(opts[2][0] != '\0')
	{
		val = atoi(opts[2]);
	} else
	{
		val = 0;
	}
	if(strcmp("-a", opts[1]) == 0)
	{
		sort = 1;
	} else
	{
		sort = 0;
	}

	Table_T tbl_Char;
	Table_T tbl_Words;
	Table_T tbl_Line;

	if(files[0][0] == '\0')
	{
		//Open temp file
		pFile = fopen(tmp_fname, "w");
		if (pFile == NULL) perror ("Error opening file");
		else
		{
			//READ FROM STDIN
			while(fgets(szString, LZMAX, stdin) != NULL) fprintf(pFile, "%s", szString);
			
			fclose(pFile);
		}
		pFile = fopen(tmp_fname, "r");
		
		tbl_Char = Table_new(256, compare);
		tbl_Words = Table_new(1000, compare);
		tbl_Line = Table_new(512, compare);
		
		if (pFile == NULL) perror ("Error opening file");
		else
		{
			createCharTable(pFile, tbl_Char);
			fseek ( pFile , 0 , SEEK_SET );
			createWordTable(pFile, tbl_Words);
			fseek ( pFile , 0 , SEEK_SET );
			createLineTable(pFile, tbl_Line);
			fclose (pFile);
		}
		Table_print(tbl_Char, val, sort);
		Table_print(tbl_Words, val, sort);
		Table_print(tbl_Line, val, sort);

		Table_free(&tbl_Char);
		Table_free(&tbl_Line);
		Table_free(&tbl_Words);
                
                remove(tmp_fname);
		return 0;
	}
	if(strcmp(opts[0], "-f") == 0)
	{
		tbl_Char = Table_new(256, compare);
		tbl_Words = Table_new(1000, compare);
		tbl_Line = Table_new(512, compare);
		//open all file and store in one table
		for(i = 0; i < argc - 1 && files[i][0] != '\0'; i++)
		{
			pFile = fopen (files[i] , "r");
			if (pFile == NULL) perror ("Error opening file");
			else
			{
				createCharTable(pFile, tbl_Char);
				fseek ( pFile , 0 , SEEK_SET );
				createWordTable(pFile, tbl_Words);
				fseek ( pFile , 0 , SEEK_SET );
				createLineTable(pFile, tbl_Line);
				fclose (pFile);
			}
		}
		Table_print(tbl_Char, val, sort);
		Table_print(tbl_Words, val, sort);
		Table_print(tbl_Line, val, sort);

		Table_free(&tbl_Char);
		Table_free(&tbl_Line);
		Table_free(&tbl_Words);
	} else
	{
		for(i = 0; i < argc - 1 && files[i][0] != '\0'; i++)
		{
			tbl_Char = Table_new(256, compare);
			tbl_Words = Table_new(1000, compare);
			tbl_Line = Table_new(512, compare);
		
			pFile = fopen (files[i] , "r");
			if (pFile == NULL) perror ("Error opening file");
			else
			{
				createCharTable(pFile, tbl_Char);
				fseek ( pFile , 0 , SEEK_SET );
				createWordTable(pFile, tbl_Words);
				fseek ( pFile , 0 , SEEK_SET );
				createLineTable(pFile, tbl_Line);
				fclose (pFile);
			}
			fprintf(stdout, "***FILE NAME: %s***\n", files[i]);
			Table_print(tbl_Char, val, sort);
			Table_print(tbl_Words, val, sort);
			Table_print(tbl_Line, val, sort);

			Table_free(&tbl_Char);
			Table_free(&tbl_Line);
			Table_free(&tbl_Words);
		}
	}
	return 0;
}
